#pragma once
#include <vector>
#include <pthread.h>
#include <string>
#include <queue>
#include<fstream>
#include<unordered_map>
//#include "dir.hpp"

using namespace std;

#define Default 3
#define pathname "./dir.text"
#define blank ":"

// dictionaries dics;

class PthreadData
{
public:
    std::string name_;
    pthread_t tid_;
};

template <class T>
class Threadpool
{
public:
    void lock()
    {
        pthread_mutex_lock(&mutex_);
    }

    void unlock()
    {
        pthread_mutex_unlock(&mutex_);
    }

    bool empty()
    {
        return rq_.empty();
    }

    int wait()
    {
        return pthread_cond_wait(&cond_, &mutex_);
    }

    void wakeup()
    {
        pthread_cond_signal(&cond_);
    }

    std::string getName(pthread_t tid)
    {
        for (auto &e : tds_)
        {
            if (e.tid_ == tid)
            {
                return e.name_;
            }
        }

        return "None";
    }

    void dictionaries()
    {
        std::ifstream in(pathname);
        std::string line;
        while (std::getline(in, line))
        {
            std::string port1;
            std::string port2;
            int pos = line.find(blank);
            if (pos == std::string::npos)
            {
                continue;
            }
            port1 = line.substr(0, pos);
            port2 = line.substr(pos + 1);

            dic.insert({port1,port2});
        }
        dic.insert({"apple","苹果..."});
        in.close();
    }

public:
    Threadpool(int num = Default) : tds_(num)
    {
        pthread_mutex_init(&mutex_, nullptr);
        pthread_cond_init(&cond_, nullptr);
        
    }

    // void TASK(T sockfd)
    // {
    //     char buf[1024];
    //     int n = read(sockfd, buf, sizeof(buf));
    //     buf[n] = 0;
    //     cout <<" get a message:" << buf << endl;
    //     string message;
    //     //message += "Server#";
    //     message += buf;
    //     write(sockfd, message.c_str(), message.size());
    //     close(sockfd);
    // }

    void TASK(T sockfd)
    {
        char buf[1024];
        int n = read(sockfd, buf, sizeof(buf));
        buf[n]= 0;
        cout << buf <<endl;
        std::string message;
        //cout<<strlen(buf)<< endl;
        auto itd=dic.find(buf);
        if(itd == dic.end())
        {
            message = "NOT";
        }
        else
        {
            message = itd->second;
        }

        // cout<<"client close sockfd"<<endl;
        // sleep(5);
        //当TCP处理数据时，发送端可能发关闭sockfd，这时可能会导致write写到一个不存在的文件，然后导致错误，
        //此时操作系统会给进程发送信号，导致服务器挂掉，
        //解决方法:signal(SIGPIPE,SIG_IGN)忽略信号
        //SIGPIPE信号产生的原因：就是客户端程序向服务器端程序发送了消息，然后关闭客户端，服务器端返回消息的时候就会收到内核给的SIGPIPE信号。
        write(sockfd, message.c_str(), message.size());
        close(sockfd);
    }

    static void *Handlertask(void *args)
    {
        Threadpool<T> *tp = static_cast<Threadpool<T> *>(args);
        std::string name = tp->getName(pthread_self());
        while (1)
        {
            tp->lock();
            while (tp->empty())
            { // 循环判断防止伪唤醒
                tp->wait();
            }
            T t = tp->pop();
            tp->unlock();

            std::cout << name<<":";
            tp->TASK(t);
            // t.getResult();
        }

        return nullptr;
    }

    void start()
    {
        for (int i = 0; i < tds_.size(); i++)
        {
            pthread_t td;
            pthread_create(&td, nullptr, Handlertask, this);
            tds_[i].tid_ = td;
            tds_[i].name_ = "thread-" + std::to_string(i);
        }
        dictionaries();
    }

    void push(T t)
    {
        rq_.push(t);
        wakeup();
    }

    T pop()
    {
        T t = rq_.front();
        rq_.pop();
        return t;
    }

    ~Threadpool()
    {
        // for (int i = 0; i < tds_.size(); i++)
        // {
        //     pthread_join(&(tds_[i].tid_), nullptr);
        // }
        pthread_mutex_destroy(&mutex_);
        pthread_cond_destroy(&cond_);
    }

private:
    std::vector<PthreadData> tds_; // 线程数量
    std::queue<T> rq_;             // 任务数量
    pthread_mutex_t mutex_;
    pthread_cond_t cond_;

    std::unordered_map<std::string, std::string> dic;
};
